package com.threeti.mecool.web.assembler;

import com.threeti.mecool.core.application.project.ProjectService;
import com.threeti.mecool.core.domain.model.acl.User;
import com.threeti.mecool.core.domain.model.project.Project;
import com.threeti.mecool.core.domain.model.project.ProjectEmployee;
import com.threeti.mecool.core.domain.model.project.ProjectSalesPromoter;
import com.threeti.mecool.core.domain.model.project.ProjectStore;
import com.threeti.mecool.core.infrastructure.persistence.ProjectCriteria;
import com.threeti.mecool.web.form.ProjectForm;
import com.threeti.mecool.web.util.DozerMapperSingleton;
import org.apache.commons.lang.StringUtils;
import org.dozer.Mapper;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.domain.Specifications;

import javax.persistence.criteria.*;
import java.util.List;
import java.util.Map;

import static com.threeti.mecool.core.infrastructure.persistence.ProjectCriteria.*;
import static org.springframework.data.jpa.domain.Specifications.where;

public abstract class ProjectAssembler {
    public static Project toDom(ProjectForm projectForm) {
        Mapper transfer = DozerMapperSingleton.getInstance();
        Project destDom = new Project();
        transfer.map(projectForm, destDom);
        return destDom;
    }

    public static Specification<Project> toCriteria(ProjectService projectService, User user, ProjectForm projForm) {
        //项目经理或创建人(通常指项目助理)->
        Specifications<Project> spec = where(eqUserId(user.getId()));

        if (user.getEmployee() != null) {
            spec = spec.or(eqProjectManager(user.getEmployee().getEmpId()));
        }
        if (user.getPermissionRole().isAdvanced()) {
            List<Long> projectIdList = projectService.findProjectIdListByOrganizationCodeList(user.getPermissionRole().getManagedOrgCodeEntries());
            spec = spec.or(ProjectCriteria.idIn(projectIdList));
        }
        //<-

        if (!projForm.hasAnyConditionInputed()) {
            return spec;
        }

        if (StringUtils.isNotBlank(projForm.getProjectName())) {
            spec = spec.and(likeProjectName(projForm.getProjectName()));
        }
        if (StringUtils.isNotBlank(projForm.getProjectCategoryIdSlt()) && !"-1".equals(projForm.getProjectCategoryIdSlt())) {
            spec = spec.and(eqProjectCategory(Long.valueOf(projForm.getProjectCategoryIdSlt())));
        }

        if (StringUtils.isNotBlank(projForm.getProjectManagerId())) {
            spec = spec.and(eqProjectManager(Long.valueOf(projForm.getProjectManagerId())));
        } else {
            if (user.getEmployee() != null) {
                spec = spec.or(eqProjectManager(user.getEmployee().getEmpId()));
            }
        }
        return spec;
    }

    public static Specification<ProjectStore> toCriteria(final Long projectId) {
        return new Specification<ProjectStore>() {
            @Override
            public Predicate toPredicate(Root<ProjectStore> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                Path<String> projectIdPath = root.get("project").get("id");
                return cb.equal(projectIdPath, projectId);
            }
        };
    }

    public static Specification toProjectEmployeeCriteria(Map<String, String> parameterMap) {

        final String projectId = parameterMap.get("projectId");
        final String titleWithinTheProject = parameterMap.get("titleWithinTheProject");
        final String empName = parameterMap.get("empName");

        Specifications<ProjectEmployee> spec = where(new Specification<ProjectEmployee>() {
            @Override
            public Predicate toPredicate(Root<ProjectEmployee> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
                Path<Long> userIdPath = root.get("project").get("id");
                return builder.equal(userIdPath, projectId);
            }
        });

        if (!StringUtils.isEmpty(titleWithinTheProject)) {
            spec = spec.and(new Specification<ProjectEmployee>() {
                public Predicate toPredicate(Root<ProjectEmployee> root,
                                             CriteriaQuery<?> query,
                                             CriteriaBuilder cb) {
                    Path<String> path = root.get("titleWithinTheProject");
                    return cb.like(path, "%" + titleWithinTheProject + "%");
                }
            });
        }

        if (!StringUtils.isEmpty(empName)) {
            spec = spec.and(new Specification<ProjectEmployee>() {
                public Predicate toPredicate(Root<ProjectEmployee> root,
                                             CriteriaQuery<?> query,
                                             CriteriaBuilder cb) {
                    Path<String> path = root.get("empName");
                    return cb.like(path, "%" + empName + "%");
                }
            });
        }

        return spec;
    }

    public static Specification<ProjectSalesPromoter> toProjectSalesPromoterCriteria(Map<String, String> parameterMap) {

        final String projectId = parameterMap.get("projectId");
        final String salesPromoterName = parameterMap.get("salesPromoterName");

        Specifications<ProjectSalesPromoter> spec = where(new Specification<ProjectSalesPromoter>() {
            @Override
            public Predicate toPredicate(Root<ProjectSalesPromoter> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
                Path<Long> userIdPath = root.get("project").get("id");
                return builder.equal(userIdPath, projectId);
            }
        });

        if (!StringUtils.isEmpty(salesPromoterName)) {
            spec = spec.and(new Specification<ProjectSalesPromoter>() {
                public Predicate toPredicate(Root<ProjectSalesPromoter> root,
                                             CriteriaQuery<?> query,
                                             CriteriaBuilder cb) {
                    Path<String> path = root.get("salesPromoter").get("name");
                    return cb.like(path, "%" + salesPromoterName + "%");
                }
            });
        }

        return spec;
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
}
